package helper

import (
	"errors"
	"fmt"
	"reflect"
	"unsafe"
)

func ListMap(data interface{}, callFun func(index int, item interface{}) interface{}) []interface{} {
	res := make([]interface{}, 0)
	sv := reflect.ValueOf(data)
	svs := sv.Slice(0, sv.Len())
	for i := 0; i < svs.Len(); i++ {
		e := svs.Index(i).Interface()
		res = append(res, callFun(i, e))
	}
	return res
}

func ListMerge(data ...interface{}) (interface{}, error) {
	if len(data) == 0 {
		return nil, nil
	}
	res := data[0].([]interface{})
	for index, item := range data {
		if index == 0 {
			continue
		}
		sv := reflect.ValueOf(item)
		svs := sv.Slice(0, sv.Len())
		for i := 0; i < svs.Len(); i++ {
			e := svs.Index(i).Interface()
			res = append(res, e)
		}
	}
	return res, nil
}

func SliceCover(origSlice interface{}, newSliceType reflect.Type) (interface{}, error) {
	sv := reflect.ValueOf(origSlice)
	if sv.Kind() != reflect.Slice {
		return nil, errors.New(fmt.Sprintf("Invalid origSlice(Non-slice value of type %T)", origSlice))
	}
	if newSliceType.Kind() != reflect.Slice {
		return nil, errors.New(fmt.Sprintf("Invalid newSliceType(non-slice type of type %T)", newSliceType))
	}

	//生成新类型的切片
	newSlice := reflect.New(newSliceType)

	//hdr指向到新生成切片的SliceHeader
	hdr := (*reflect.SliceHeader)(unsafe.Pointer(newSlice.Pointer()))

	var newElemSize = int(sv.Type().Elem().Size()) / int(newSliceType.Elem().Size())

	//设置SliceHeader的Cap，Len，以及数组的ptr
	hdr.Cap = sv.Cap() * newElemSize
	hdr.Len = sv.Len() * newElemSize
	hdr.Data = uintptr(sv.Pointer())
	return newSlice.Elem().Interface(), nil
}

func SlicePage(originData []map[string]interface{}, page int, pageSize int) map[string]interface{} {
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 {
		pageSize = 30
	}
	startIndex := (page - 1) * pageSize
	if startIndex > len(originData) {
		return map[string]interface{}{
			"list":      make([]map[string]interface{}, 0),
			"page":      page,
			"page_size": pageSize,
			"total":     len(originData),
		}
	}
	endIndex := startIndex + pageSize
	if endIndex > len(originData) {
		endIndex = len(originData)
	}
	return map[string]interface{}{
		"list":      originData[startIndex:endIndex],
		"page":      page,
		"page_size": pageSize,
		"total":     len(originData),
	}
}
